package main

import (
	"fmt"
	"os"
	"syscall"
	"unsafe"
)

type IMAGE_DOS_HEADER struct {
	e_magic    [2]byte
	e_cblp     uint16
	e_cp       uint16
	e_crlc     uint16
	e_cparhdr  uint16
	e_minalloc uint16
	e_maxalloc uint16
	e_ss       uint16
	e_sp       uint16
	e_csum     uint16
	e_ip       uint16
	e_cs       uint16
	e_lfarlc   uint16
	e_ovno     uint16
	e_res      [4]byte
	e_oemid    uint16
	e_oeminfo  uint16
	e_res2     [10]byte
	e_lfanew   uint32
}

func main() {
	// 创建一个新的可执行文件
	exe, err := os.Create("my_program.exe")
	if err != nil {
		panic(err)
	}
	defer exe.Close()

	// 设置可执行文件的头部信息
	dos_header := make([]byte, 64)
	*(*uint32)(unsafe.Pointer(&header[0])) = 0x4550
	*(*uint32)(unsafe.Pointer(&header[1])) = 0x0090
	*(*uint32)(unsafe.Pointer(&header[0])) = 0x0003
	*(*uint32)(unsafe.Pointer(&header[0])) = 0x0000
	*(*uint32)(unsafe.Pointer(&header[0])) = 0x0000

	// 写入头部信息到可执行文件
	_, err = exe.Write(dos_header)
	if err != nil {
		panic(err)
	}

	// 创建一个新的节区
	section := make([]byte, 4096)
	*(*uint32)(unsafe.Pointer(&section[0])) = 0xE0000020                      // Section type
	*(*uint32)(unsafe.Pointer(&section[4])) = 0x00000000                      // Virtual address
	*(*uint32)(unsafe.Pointer(&section[8])) = 0x40000000                      // Virtual size
	*(*uint32)(unsafe.Pointer(&section[12])) = 0x00000040                     // Raw size
	*(*uint32)(unsafe.Pointer(&section[16])) = 0x00000040                     // Pointer to raw data
	*(*uint32)(unsafe.Pointer(&section[20])) = 0x00000040                     // Pointer to relocations
	*(*uint32)(unsafe.Pointer(&section[24])) = 0x00000040                     // Pointer to line numbers
	*(*uint16)(unsafe.Pointer(&section[28])) = 0x0000                         // Number of relocations
	*(*uint16)(unsafe.Pointer(&section[30])) = 0x0000                         // Number of line numbers
	*(*uint32)(unsafe.Pointer(&section[32])) = syscall.PAGE_EXECUTE_READWRITE // Characteristics

	// 写入节区信息到可执行文件
	_, err = exe.Write(section)
	if err != nil {
		panic(err)
	}

	// 写入程序代码到可执行文件
	code := []byte{
		0xB8, 0x01, 0x00, 0x00, 0x00, // mov eax, 1
		0xC3, // ret
	}
	_, err = exe.Write(code)
	if err != nil {
		panic(err)
	}

	fmt.Println("PE file generated successfully!")
}
